﻿using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Printing;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;

namespace FileToVideo.Helpers
{
    /// <summary>
    /// 工具类
    /// </summary>
    public class Item
    {
        /// <summary>
        /// 日志打印器
        /// </summary>
        public static Logger logger = new();

        /// <summary>
        /// 选择的文件夹路径
        /// </summary>
        private static string ChousePath = "";

        /// <summary>
        /// SHA256签名
        /// (不适用于签名中文内容,中文加密和js上的加密不同)
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string SHA256(string data)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(data);
            byte[] hash = System.Security.Cryptography.SHA256.Create().ComputeHash(bytes);

            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }

            return builder.ToString();
        }

        /// <summary>
        /// MD5签名
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string MD5(string data)
        {
            var bytes = Encoding.UTF8.GetBytes(data);
            var hash = System.Security.Cryptography.MD5.Create().ComputeHash(bytes);

            var builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("x2"));
            }

            return builder.ToString();
        }

        /// <summary>
        /// MD5签名
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string MD5(byte[] data)
        {
            var hash = System.Security.Cryptography.MD5.Create().ComputeHash(data);

            var builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("x2"));
            }

            return builder.ToString();
        }

        /// <summary>
        /// 新建一个UID
        /// </summary>
        /// <returns></returns>
        public static string NewUUID()
        {
            return NewUUID(DateTime.Now.ToJSTime().ToString());
        }

        /// <summary>
        /// 新建一个UID
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string NewUUID(string input)
        {
            input = MD5(input);
            var sha = SHA256(input);
            var uuid = "uuxxxuuy-1xxx-7xxx-yxxx-xxx0xxxy";
            var temp = new StringBuilder();
            var dex = new StringBuilder();
            for (int i = 0; i < uuid.Length; i++)
            {
                var e = uuid[i];
                if (e == 'u')
                {
                    temp.Append(sha[2 * i]);
                    dex.Append(sha[2 * i]);
                }
                else if (e == 'x')
                {
                    temp.Append(input[i]);
                    dex.Append(input[i]);
                }
                else if (e == 'y')
                {
                    temp.Append(MD5(dex.ToString())[i]);
                }
                else
                {
                    temp.Append(e);
                }
            }
            uuid = temp.ToString();
            return uuid;
        }

        /// <summary>
        /// 选择文件夹
        /// </summary>
        /// <param name="label">选择文件夹地址</param>
        /// <param name="tishi">选择时候提示内容</param>
        public static void ChoiceFolder(ref string label, string tishi)
        {
            ChoiceFolder(ref label, tishi, Environment.SpecialFolder.MyDocuments);
        }

        /// <summary>
        /// 选择文件夹 (WPF版本)
        /// </summary>
        /// <param name="label">选择文件夹地址</param>
        /// <param name="tishi">选择时候提示内容</param>
        /// <param name="path">已经存在的文件路径</param>
        public static void ChoiceFolder(ref string label, string tishi, string path)
        {
            var dialog = new OpenFolderDialog();
            dialog.Title = tishi;

            if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
            {
                dialog.InitialDirectory = path;
            }

            bool? result = dialog.ShowDialog();

            if (result == true)
            {
                if (string.IsNullOrEmpty(dialog.FolderName))
                {
                    return;
                }

                path = dialog.FolderName;
                label = path;
            }
        }

        /// <summary>
        /// 选择文件夹 (WPF版本)
        /// </summary>
        /// <param name="label">选择文件夹地址</param>
        /// <param name="tishi">选择时候提示内容</param>
        /// <param name="folder">系统文件夹枚举项</param>
        public static bool ChoiceFolder(ref string label, string tishi, Environment.SpecialFolder folder)
        {
            var dialog = new OpenFolderDialog();
            dialog.Title = tishi;

            // 获取系统文件夹路径
            string systemFolderPath = Environment.GetFolderPath(folder);

            // 设置初始目录
            if (!string.IsNullOrEmpty(ChousePath) && Directory.Exists(ChousePath))
            {
                dialog.InitialDirectory = ChousePath;
            }
            else if (!string.IsNullOrEmpty(systemFolderPath) && Directory.Exists(systemFolderPath))
            {
                dialog.InitialDirectory = systemFolderPath;
            }

            bool? result = dialog.ShowDialog(Application.Current.MainWindow);

            if (result == true && !string.IsNullOrEmpty(dialog.FolderName))
            {
                ChousePath = dialog.FolderName;
                label = ChousePath;
                return true;
            }
            else
            {
                // 用户取消时，保持原有值不变
                return false;
            }
        }

        /// <summary>
        /// 选择指定文件 (保持原有接口)
        /// </summary>
        /// <param name="label"></param>
        /// <param name="tishi">选择时候提示内容</param>
        /// <param name="folder">系统文件夹枚举项</param>
        /// <param name="name">限定文件，例如："*.txt" 或 "文本文件|*.txt"</param>
        /// <param name="fileExists">文件是否存在(默认存在)</param>
        public static void ChoiceFile(ref string label, string tishi, Environment.SpecialFolder folder, string name, bool fileExists = true)
        {
            var openDialog = new OpenFileDialog();

            // 设置初始目录
            string initialDirectory = Environment.GetFolderPath(folder);
            if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory))
            {
                openDialog.InitialDirectory = initialDirectory;
            }

            // 设置文件存在检查 - 这是关键修复
            openDialog.CheckFileExists = fileExists;
            openDialog.CheckPathExists = true;

            // 智能处理过滤器格式
            string filter = name;
            if (!name.Contains("|"))
            {
                // 如果只是扩展名，如 "*.txt"，则自动格式化为友好名称
                string extension = Path.GetExtension(name);
                string displayName = extension switch
                {
                    ".mp4" => "MP4视频文件",
                    ".txt" => "文本文件",
                    ".json" => "JSON文件",
                    ".xml" => "XML文件",
                    ".csv" => "CSV文件",
                    ".xlsx" => "Excel文件",
                    ".docx" => "Word文档",
                    ".pdf" => "PDF文档",
                    ".jpg" => "JPEG图像",
                    ".png" => "PNG图像",
                    _ => "文件"
                };
                filter = $"{displayName}|{name}";
            }

            openDialog.Filter = filter;
            openDialog.FilterIndex = 1;
            openDialog.RestoreDirectory = true;
            openDialog.Title = tishi;

            bool? result = openDialog.ShowDialog(Application.Current.MainWindow);

            if (result == true && !string.IsNullOrEmpty(openDialog.FileName))
            {
                // 如果用户只输入了文件名（没有扩展名），自动添加扩展名
                string selectedFile = openDialog.FileName;

                // 获取过滤器中的第一个扩展名
                string targetExtension = GetPrimaryExtension(filter);
                if (targetExtension==null)
                {
                    throw new Exception("扩展名不存在!");
                }

                // 如果用户输入的文件名没有扩展名，自动添加
                if (!string.IsNullOrEmpty(targetExtension) &&
                    !Path.HasExtension(selectedFile) &&
                    !fileExists) // 只有在选择新文件时才自动添加扩展名
                {
                    string cleanExtension = targetExtension.Replace("*", "");
                    selectedFile = Path.Combine(Path.GetDirectoryName(selectedFile),
                                              Path.GetFileNameWithoutExtension(selectedFile) + cleanExtension);
                }

                Log(selectedFile);
                label = selectedFile;
            }
        }

        /// <summary>
        /// 从过滤器中提取主要扩展名
        /// </summary>
        private static string? GetPrimaryExtension(string filter)
        {
            try
            {
                // 格式： "MP4视频文件|*.mp4"
                if (filter.Contains("|"))
                {
                    string extensionsPart = filter.Split('|')[1];
                    var extensions = extensionsPart.Split(';');
                    return extensions[0]; // 返回第一个扩展名，如 "*.mp4"
                }
                return filter; // 直接返回如 "*.mp4"
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 打印内容
        /// </summary>
        /// <param name="value"></param>
        private static void Log(string value)
        {
            logger.Log(value);
        }

        /// <summary>
        /// 使用cmd命令
        /// </summary>
        /// <param name="cmdCode"></param>
        public static void UseCmd(string cmdCode)
        {
            System.Diagnostics.Process proIP = new System.Diagnostics.Process();
            proIP.StartInfo.FileName = "cmd.exe";
            proIP.StartInfo.UseShellExecute = false;
            proIP.StartInfo.RedirectStandardInput = true;
            proIP.StartInfo.RedirectStandardOutput = true;
            proIP.StartInfo.RedirectStandardError = true;
            proIP.StartInfo.CreateNoWindow = true;
            proIP.Start();
            proIP.StandardInput.WriteLine(cmdCode);
            proIP.StandardInput.WriteLine("exit");
            string strResult = proIP.StandardOutput.ReadToEnd();
            Console.WriteLine(strResult);
            proIP.Close();
        }

        /// <summary>
        /// 判断dll是否能用
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static bool IsAssemblyLoaded(string assemblyName)
        {
            return AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.GetName().Name == assemblyName);
        }

        /// <summary>
        /// 获取dll位置
        /// 找不到会报错
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        public static string GetDllPath(string assemblyName)
        {
            var assembly = System.Reflection.Assembly.Load(assemblyName);
            return assembly.Location;
        }

        /// <summary>
        /// 打开网站|其他东西 (WPF改进版本)
        /// </summary>
        /// <param name="web">网址|地址</param>
        public static void OpenOnWindows(string web)
        {
            try
            {
                // 确保web参数不为空
                if (string.IsNullOrWhiteSpace(web))
                {
                    MessageBox.Show("地址不能为空", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                // 处理URL格式（如果缺少协议头，自动添加http://）
                string processedUrl = web;
                if (!web.StartsWith("http://") && !web.StartsWith("https://") &&
                    !web.StartsWith("ftp://") && !web.StartsWith("file://"))
                {
                    // 检查是否是文件路径
                    if (System.IO.Path.IsPathRooted(web) || web.Contains(":\\") || web.Contains("/"))
                    {
                        // 可能是文件路径，不需要添加http://
                    }
                    else
                    {
                        // 可能是网址，添加https://
                        processedUrl = "https://" + web;
                    }
                }

                // 使用ProcessStartInfo以提高安全性
                ProcessStartInfo startInfo = new ProcessStartInfo
                {
                    FileName = processedUrl,
                    UseShellExecute = true // 使用系统shell打开，这是关键
                };

                Process.Start(startInfo);
            }
            catch (Exception ex)
            {
                // 处理异常，例如浏览器未安装等情况
                MessageBox.Show($"无法打开地址: {ex.Message}", "错误",
                               MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="path"></param>
        public static void OpenFile(string path)
        {
            var command = string.Format("explorer /select,{0}", path);
            UseCmd(command);
        }

        /// <summary>
        /// 根据INI内容创建regex对象
        /// </summary>
        /// <param name="iniValue"></param>
        /// <returns></returns>
        public static Regex CreateRegex(string iniValue)
        {
            if (iniValue == null)
            {
                return new Regex("");
            }
            var read = new Regex("^[\"']?([^\r\n]+)[\"']?$");
            var value = read.Match(iniValue);
            if (value.Success)
            {
                var regex = new Regex(value.Groups[1].ToString());
                return regex;
            }
            else
            {
                return new Regex(iniValue);
            }
        }

        /// <summary>
        /// 将regex对象转为ini内容
        /// </summary>
        /// <param name="regex"></param>
        /// <returns></returns>
        public static string RegexToIni(Regex regex)
        {
            var sb = new StringBuilder();
            sb.Append('"');
            sb.Append(regex.ToString());
            sb.Append('"');
            return sb.ToString();
        }

        /// <summary>
        /// 或者
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t1"></param>
        /// <param name="t2"></param>
        /// <returns></returns>
        public static T Or<T>(T t1, T t2) where T : class
        {
            if (t1 == null)
            {
                return t2;
            }
            else
            {
                return t1;
            }
        }

        /// <summary>
        /// 或者
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t1"></param>
        /// <param name="getT2"></param>
        /// <returns></returns>
        public static T Or<T>(T t1, Func<T> getT2) where T : class
        {
            if (t1 == null)
            {
                return getT2();
            }
            else
            {
                return t1;
            }
        }
    }
}